﻿//【进阶】41.C++11(3)
//【头文件包含】
//C++的主要头文件
#include<iostream>//c++的输入输出流
using namespace std;
#include<algorithm>
#include<string>
#include<vector>
#include<list>
//C的主要头文件
//#include<stdio.h>
//#include<stdlib.h>
//#include<assert.h>
//#include<string.h> 
#include <thread>
#include <mutex>
#include <atomic>

//【命名空间】

//【类声明】
struct Goods
{
	string _name;
	double _price;
};
struct Compare
{
	bool operator()(const Goods& gl, const Goods& gr)
	{
		return gl._price <= gr._price;
	}
};


mutex  mtx;//互斥锁
//int x = 0;
atomic<int> x = 0;//使用原子的++ -- 则可以不用加互斥锁

struct ADD
{
	void operator()(int n)
	{
		for (int i = 0;i < n;++i)
		{
			++x;
		}
	}
};
//【函数声明】
void Test1();void Test2();void Test3();void Test4();
void Add(int n)
{
	//mtx.lock();//上锁
	for (int i = 0;i < n;++i)
	{
		++x;
	}
	//mtx.unlock();//解锁
}

//【主函数】
int main()
{
	cout << "****主函数开始****" << endl;
	Test1();
	Test2();
	Test3();
	Test4();
	cout << "****主函数结束****" << endl;
	return 0;
}

//【函数定义】

/*测试用例*/void Test1()
{
	cout << "****测试用例开始****"<< endl;
	// 最简单的lambda表达式, 该lambda表达式没有任何意义
	[] {};

	// 省略参数列表和返回值类型，返回值类型由编译器推导为int
	int a = 3, b = 4;


	auto add1 = [](int x1, int x2)->int {return x1 + x2;};
	cout << add1(a, b) << endl;

	//直接捕捉(复制捕捉)
	auto add2 = [a, b]()->int {return a + b;};
	cout << add2() << endl;

	//全部捕捉
	auto add3 = [=] {return a + 3; };
	cout << add3() << endl;

	// 省略了返回值类型，无返回值类型
	auto add4 = [&](int c) {b = a + c; };
	add4(10);
	cout << a << " " << b << endl;

	//各部分都很完善的lambda函数
	auto add5 = [=, &b](int c)->int {return b += a + c; };
	cout << add5(10) << endl;
	
	
	cout << "****测试用例结束****" << endl << endl;
}

/*测试用例*/void Test2()
{
	cout << "****测试用例开始****" << endl;
	//函数指针配合thread
	thread t1(Add, 1000000);
	thread t2(Add, 1000000);
	t1.join();
	t2.join();
	cout << x << endl;
	cout << "****测试用例结束****" << endl<<endl;
}

/*测试用例*/void Test3()
{
	cout << "****测试用例开始****" << endl;
	//仿函数配合thread
	ADD add;
	thread t1(add, 1000000);
	thread t2(ADD(), 1000000);
	t1.join();
	t2.join();
	cout << x << endl;

	//lambda表达式配合thread
	atomic<int> y = 0;//使用原子的++ -- 则可以不用加互斥锁
	auto aDD = [&y](int n) {for (int i = 0;i < n;++i)
	{
		++y;
	}};
	thread t3(aDD, 1000000);
	thread t4(aDD, 1000000);
	t3.join();
	t4.join();
	cout << y << endl;

	cout << "****测试用例结束****" << endl << endl;
}

/*测试用例*/void Test4()
{
	cout << "****测试用例开始****" << endl;
	//m个线程
	atomic<int> c = 0;//使用原子的++ -- 则可以不用加互斥锁
	int m = 4;
	int n = 1000000;
	vector<thread> vthreads;
	for (int i = 0;i < m;++i)
	{
		vthreads.push_back(thread([&c](int n) {for (int i = 0;i < n;++i)
		{
			++c;
		}}, n));
	}
	for (auto& t : vthreads)
	{
		cout << t.get_id() << "jion" << endl;
		t.join();
	}
	cout << c << endl;

	cout << "****测试用例结束****" << endl << endl;
}




//【笔记】
//【进阶】41.C++11
	//lambda表达式 
		// lambda表达式书写格式：
		// [capture-list] (parameters) mutable -> return-type { statement }
			// 参数列表 - (parameters)
				// 与普通函数的参数列表一致，不传参则省略
			// 取消常量性 - mutable
				// 默认情况下lambda函数总是const函数，显示mutable可以取消常量属性，使用时则不能省略参数列表
			// 返回值类型 - ->returntype
				// 没返回值或返回值类型明确是可以省略，有编译器进行推导
			// 函数体 - {statement}
				// 函数体内为函数实现代码，除可使用参数列表的参数外还可使用所有捕获到的变量
		//lambda的底层原理类似仿函数，调用时会生成一个临时的类，在类中重载operator()
	//线程库
		// windows下使用自己的一套API如CreateThread
		// Linux下使用posix的pthread如pthread_create
		//C++98中如果需要多线程使用条件编译
			//#ifdef _WIN32
			//    CreateThread(...)
			//#else
			//	  pthread_create(...)
			//#endif
		//C++11支持线程库，面向对象封装，特点是跨平台
		// 封装库中使用了条件编译，再在底层分别调用不同平台线程API
		// thread是多线程相关的库；mutex是互斥锁相关的库
		// 在多线程过程存在非原子操作
			// 利用互斥锁来使子线程变成串行 
			// 还可利用atomic 创建原子对象进行原子操作



		









